import RopeAssembler from "../Assembers/RopeAssembler";
import RolpAssembler from "../Assembers/RopeAssembler";

const { ccclass, property } = cc._decorator;
const gfx = cc['gfx'];


@ccclass
// @executeInEditMode
export default class RopeSprite extends cc.Sprite {

    _assembler: RolpAssembler = null;
    @property
    _jointCount: number = 5;
    @property({
        type: cc.Integer,
        tooltip: '绳子节数，节数越多效果越好'
    })
    get jointCount(): number {
        return this._jointCount;
    }
    set jointCount(v: number) {
        if (v > 0) {
            this._jointCount = v;
            this.initPoints();
        }
    }
    points: cc.Vec2[] = [];
    get vertexesCount() {
        return (this.jointCount + 1) * 2;
    }
    @property
    isFixTail: boolean = false;
    @property
    gravity = -9.8;
    updateVertexes() {
        //@ts-ignore
        let assembler = this._assembler;
        if (!assembler) {
            return;
        }

        this.setVertsDirty();
    }

    onEnable() {
        super.onEnable();
        window['rolpSprite'] = this;
    }
    // 末位点
    set tailPos(endPos: cc.Vec2) {
        this.points[this.points.length - 1] = endPos;
    }
    get tailPos(): cc.Vec2 {
        return this.points[this.points.length - 1];
    }
    // 初始化顶点
    /** 更新一次顶点位置和uv，后面不再改动uv */
    initPoints() {
        let cw = this.node.width, ch = this.node.height;
        // 初始化一次顶点
        let pointCount = this.jointCount + 1;
        let interval = ch / this.jointCount;
        this.points = [];
        for (let i = 0; i < pointCount; i++) {
            this.points[i] = cc.v2(0, -interval * i);
        }
        console.log('this.points', this.points);
    }
    // 更新重力、加速度
    simulate() {
        let cw = this.node.width, ch = this.node.height;
        let defaultWidth = ch / (this.points.length - 1)
        let velocity = cc.v2();
        let gravity = cc.v2(0, this.gravity * this.dt)
        for (let i = 0; i < this.points.length - 1; i++) {
            let point = this.points[i]
            let oldPos = point['oldPos'];
            if (oldPos) {
                velocity = point.sub(oldPos).normalize().mul(0.5);
                point.addSelf(velocity)
                point.addSelf(gravity)
            }
        }
    }
    /**更新约束 */
    applyConstraint() {
        let cw = this.node.width, ch = this.node.height;
        let defaultWidth = ch / (this.points.length - 2)
        for (let k = 0; k < 20; k++) {
            // 从倒二个点开始遍历到第一个点
            if (this.points.length > 2) {
                for (let i = this.points.length - 1; i >= 1; i--) {
                    let secondPoint = this.points[i];
                    let firstPoint = this.points[i - 1];
                    // debugger
                    // console.log('secondPoint', secondPoint, i)
                    let dir = secondPoint.sub(firstPoint);
                    let dist = dir.mag();
                    let vector = cc.v2();
                    if (dist > defaultWidth) {
                        vector = dir.normalize();
                    } else if (dist < defaultWidth) {
                        vector = dir.normalize().neg();
                    } else {
                        continue;
                    }
                    let fixLen = Math.abs(dist - defaultWidth);
                    secondPoint['oldPos'] = secondPoint;
                    if (this.isFixTail && i >= this.points.length - 1) {
                        vector.mulSelf(fixLen);
                        firstPoint.addSelf(vector)
                    } else if (i == 1) {
                        secondPoint.subSelf(vector.mul(fixLen))
                    } else if (i > 1) {
                        vector.mulSelf(fixLen * 0.5);
                        firstPoint.addSelf(vector)
                        secondPoint.addSelf(vector.neg())
                    }
                }
            }
        }
    }
    // 更新顶点
    draw() {
        this.setVertsDirty();
    }

    dt: number = 0;
    update(dt: number) {
        this.dt = dt;
        this.simulate();
        this.applyConstraint();
    }
    lateUpdate() {

        this.draw();
        // GameHelper.clearDraw();
        // let list = [];
        // for (let i of this.points) {
        //     list.push(this.node.convertToWorldSpaceAR(i));
        // }
        // GameHelper.drawAny(null, list);
    }

    _resetAssembler() {
        // this.setVertsDirty();
        this.initPoints();
        let assembler = this._assembler = new RopeAssembler();
        assembler.init(this);

        //@ts-ignore
        this._updateColor();
    }
}
